package com.xjscrm.console.mq.consumer;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.uzai.mobile.collect.api.MicaTopics;
import com.uzai.mobile.collect.api.dto.MicaTriggerDto;
import com.uzai.mobile.collect.api.dto.trigger.sns.MicaTriggerPublishSnsMsg;
import com.uzai.mobile.collect.api.enums.MicaTriggerType;
import com.uzai.trace.TraceGenerate;
import com.xjscrm.common.entity.WwDevice;
import com.xjscrm.common.entity.WwTags;
import com.xjscrm.common.enums.RedisCacheKeyEnum;
import com.xjscrm.console.dto.circle.CircleTaskMqDTO;
import com.xjscrm.console.dto.circle.CircleVisibleDTO;
import com.xjscrm.console.entity.CircleTask;
import com.xjscrm.console.entity.CircleTaskPublish;
import com.xjscrm.console.mapper.CircleTaskPublishMapper;
import com.xjscrm.console.mapper.WwTagsMapper;
import com.xjscrm.console.mq.producer.SendMsgProducer;
import com.xjscrm.console.service.customer.circle.CircleTaskPublishService;
import com.xjscrm.console.service.customer.circle.CircleTaskService;
import com.xjscrm.console.service.customer.wwCustomer.WwCustomerMatchService;
import com.xjscrm.console.service.customer.wwDevice.WwDeviceService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RocketMQMessageListener(topic = "xj_circle_send_topic", consumerGroup = "xj_circle_send_group", messageModel = MessageModel.CLUSTERING)
@Component
@Slf4j
public class SendCircleMessageConsumer implements RocketMQListener<CircleTaskMqDTO> {

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    private CircleTaskService circleTaskService;
    @Autowired
    private WwDeviceService wwDeviceService;
    @Autowired
    private CircleTaskPublishMapper circleTaskPublishMapper;
    @Autowired
    private SendMsgProducer sendMsgProducer;
    @Autowired
    private WwTagsMapper wwTagsMapper;
    @Autowired
    private Executor chatExecutor;
    @Autowired
    private CircleTaskPublishService circleTaskPublishService;
    @Autowired
    private WwCustomerMatchService wwCustomerMatchService;

    @Override
    @TraceGenerate
    public void onMessage(CircleTaskMqDTO message) {

        log.info("收到发送执行朋友圈任务的消息: {}", message);

        Long merId = message.getMerId();
        Long taskId = message.getTaskId();

        chatExecutor.execute(() -> this.doSend(merId, taskId));
    }

    private void doSend(Long merId, Long taskId) {

        String format = String.format("xj_send_circle_task_flag_%s", taskId);
        //
        if (Boolean.FALSE.equals(redisTemplate.opsForValue().setIfAbsent(format, taskId, 60, TimeUnit.SECONDS))) {
            log.info("当前朋友圈任务已被其他节点处理, 消息将被忽略");
            return;
        }

        try {
            CircleTask circleTask = circleTaskService.getById(merId, taskId);

            if (!Lists.newArrayList(21, 20).contains(circleTask.getStatus())) {
                log.info("朋友圈任务状态非待执行, 将被忽略");
                return;
            }

            //
            if (circleTaskService.setTaskStatusIsExecuting(merId, circleTask.getId())) {
                List<CircleTaskPublish> circleTaskPublishes = circleTaskPublishMapper.selectListByTaskId(merId, circleTask.getId());

                long current = System.currentTimeMillis() / 1000L;

                for (CircleTaskPublish circleTaskPublish : circleTaskPublishes) {

                    if (!Objects.equals(circleTaskPublish.getStatus(), 30)) {
                        continue;
                    }

                    Long deviceUniqueId = circleTaskPublish.getDeviceUniqueId();

                    WwDevice device = wwDeviceService.getById(merId, deviceUniqueId);

                    String cacheKey = String.format(RedisCacheKeyEnum.WW_DEVICE_LAST_HEAT_BEAT_TIME.getKey(), device.getDeviceId());
                    Integer lastHeartBeat = (Integer) redisTemplate.opsForValue().get(cacheKey);

                    if (Objects.isNull(lastHeartBeat) || current - lastHeartBeat > 300) {
                        circleTaskPublishService.updatePublishFailWithOffline(merId, circleTaskPublish.getId());
                        continue;
                    }

                    MicaTriggerPublishSnsMsg r = new MicaTriggerPublishSnsMsg();
                    r.setMessageId(circleTaskPublish.getId());
                    r.setId(circleTaskPublish.getId());
                    r.setContent(circleTask.getText());
                    r.setType(circleTask.getContentType());

//                    String visibleCondition = circleTask.getVisibleCondition();
//                    if (StringUtils.isNotBlank(visibleCondition)) {
//                        CircleVisibleDTO circleVisibleDTO = JSON.parseObject(visibleCondition, CircleVisibleDTO.class);
//                        r.setVisibleWxIds(
//                                this.findVisibleWxIds(merId, circleVisibleDTO)
//                        );
//                    }

                    switch (circleTask.getContentType()) {
                        case 0:
                            List<String> imgUrls = JSON.parseArray(circleTask.getImgs(), String.class);
                            log.info("imgUrls: {}", imgUrls);
                            r.setMediaUrlList(imgUrls);
                            break;
                        case 1:
                            r.setMediaUrlList(Lists.newArrayList(circleTask.getVideos()));
                            break;
                        case 2:
                            r.setMediaUrlList(Lists.newArrayList(circleTask.getLink()));
                            break;
                    }

                    if (StringUtils.isNoneBlank(circleTask.getComments())) {
                        List<String> comments = JSON.parseArray(circleTask.getComments(), String.class);
                        r.setComments(comments);
                    }

                    if (StringUtils.isNotBlank(circleTask.getVisibleTags())) {
                        List<Long> longs = JSON.parseArray(circleTask.getVisibleTags(), Long.class);
                        List<WwTags> wwTags = wwTagsMapper.selectListByIds(merId, longs);
                        if (ObjectUtils.isNotEmpty(wwTags)) {
                            List<Long> tagIds = wwTags.stream().map(WwTags::getTagId).filter(StringUtils::isNotBlank).map(Long::parseLong).distinct().collect(Collectors.toList());
                            r.setVisibleTags(tagIds);
                        }
                    }

                    MicaTriggerDto micaTriggerDto = MicaTriggerDto.newInstance(r, MicaTriggerType.TRIGGER_PUBLISH_SNS, item -> {
                        item.setReqId(circleTaskPublish.getId());
                        item.setDeviceId(device.getDeviceId());
                        item.setDeviceType(device.getDeviceType());
                    });

                    sendMsgProducer.pushMsg(micaTriggerDto, MicaTopics.WW_TRIGGER_TOPIC);

                    // 更新发送时间
                    circleTaskPublishMapper.updateStatusToSending(circleTaskPublish.getMerId(), circleTaskPublish.getId());
                }
            }
        } finally {
            redisTemplate.expire(format, 0, TimeUnit.SECONDS);
        }
    }

    private List<String> findVisibleWxIds(Long merId, CircleVisibleDTO circleVisibleDTO) {

        String customerCreateDayStart = circleVisibleDTO.getCustomerCreateDayStart();
        String customerCreateDayEnd = circleVisibleDTO.getCustomerCreateDayEnd();

        Integer startTime = null;
        Integer endTime = null;
        Boolean hasRemark = null;
        Integer gender = null;

        //
        if (!StringUtils.isAllBlank(customerCreateDayStart, customerCreateDayEnd)) {
            DateTime parse = DateUtil.parse(customerCreateDayStart, "yyyy-MM-dd");
            startTime = Math.toIntExact(DateUtil.beginOfDay(parse).getTime() / 1000L);
            DateTime parse1 = DateUtil.parse(customerCreateDayEnd, "yyyy-MM-dd");
            endTime = Math.toIntExact(DateUtil.endOfDay(parse1).getTime() / 1000L);
        }
        //
        if (Objects.nonNull(circleVisibleDTO.getCustomerRemarkOpt())) {
            hasRemark = Objects.equals(circleVisibleDTO.getCustomerRemarkOpt(), 1);
        }
        //
        if (Objects.nonNull(circleVisibleDTO.getCustomerGenders())) {
            gender = circleVisibleDTO.getCustomerGenders();
        }
        // 获取到匹配的客户id集合
        List<Long> matchCustomerWithCondition = wwCustomerMatchService.matchCustomerWithCondition(merId, gender, hasRemark, startTime, endTime);

        List<Long> excludeCustomerIds = new ArrayList<>();
        //
        if (Objects.equals(circleVisibleDTO.getCustomerExcludeCondition(), 1)) {
            String customerExcludeEnterpriseTags = circleVisibleDTO.getCustomerExcludeEnterpriseTags();

            if (StringUtils.isNotBlank(customerExcludeEnterpriseTags)) {
                List<Long> excludeTagIds = JSON.parseArray(customerExcludeEnterpriseTags, Long.class);
                switch (circleVisibleDTO.getCustomerExcludeEnterpriseTagOpt()) {
                    case 0:
                        excludeCustomerIds = wwCustomerMatchService.matchCustomerWithAllTag(merId, excludeTagIds);
                        break;
                    case 1:
                        excludeCustomerIds = wwCustomerMatchService.matchCustomerWithAnyTag(merId, excludeTagIds);
                        break;
                    case 2:
                        excludeCustomerIds = wwCustomerMatchService.matchCustomerWithNoneTag(merId);
                        break;
                }
            }
        }
        //
        if (Objects.equals(circleVisibleDTO.getCustomerExcludeNewUserOpt(), 1)) {
            DateTime r = DateUtil.date();
            DateTime start = DateUtil.beginOfDay(r);
            DateTime end = DateUtil.endOfDay(r);
            List<Long> newCustomerIds = wwCustomerMatchService.matchCustomerWithAddTime(merId, Math.toIntExact(start.getTime() / 1000L), Math.toIntExact(end.getTime() / 1000L));
            excludeCustomerIds.addAll(newCustomerIds);
        }

        Set<Long> longs = CollUtil.intersectionDistinct(matchCustomerWithCondition, excludeCustomerIds);

        return longs.stream().map(Object::toString).collect(Collectors.toList());
    }
}